package com.zf.virtual_thread.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;

/**
 * 虚拟线程测试类
 * 前提：开启 `spring.threads.virtual.enabled=true`
 */
@Slf4j
@RestController
@RequestMapping("/vt")
public class VirtualThreadTestController {

    /**
     * <pre>
     * 同步接口：
     * <p>
     * 1、内嵌的 Tomcat、Jetty 已经适配了虚拟线程，开启 `spring.threads.virtual.enabled=true` 后， Tomcat、Jetty 都会使用虚拟线程来处理请求。
     * 2、目前 Undertow 暂未适配虚拟线程，所以还是使用平台线程处理请求。
     * </pre>
     */
    @GetMapping("/plain")
    public String plain() throws InterruptedException {
        // Tomcat、Jetty 打印虚拟线程名称:
        // VirtualThread[#虚拟线程id,虚拟线程名称]/挂载到的平台线程的状态@挂载到的平台线程的名称
        // VirtualThread[#82,task-8]/runnable@ForkJoinPool-1-worker-1

        // Undertow 会打印平台线程:
        // Thread[#69,task-1,5,main]

        String ts = Thread.currentThread().toString();
        System.out.println(ts);
        // TimeUnit.MILLISECONDS.sleep(250);
        return "plain result";

    }

    /**
     * Callable<T>类型异步接口：使用虚拟线程
     */
    @GetMapping("/callable")
    public Callable<String> callable() {
        return () -> {
            // 打印虚拟线程名称
            // VirtualThread[#虚拟线程id,虚拟线程名称]/挂载到的平台线程的状态@挂载到的平台线程的名称
            // VirtualThread[#82,task-8]/runnable@ForkJoinPool-1-worker-1
            String ts = Thread.currentThread().toString();
            System.out.println(ts);
            return "callable result";
        };
    }

    /**
     * <pre>
     * 使用 @Async 注解的异步接口：
     *
     * 1、必须先使用 @EnableAsync 启用 @Async，这样无论 Tomcat、Jetty、Undertow都会使用虚拟线程。
     * 2、如果没有使用 @EnableAsync，则：
     *      2.1、目前 Undertow 暂未适配虚拟线程，所以还是使用平台线程处理请求。
     *      2.2、Tomcat、Jetty 已经适配了虚拟线程，会使用虚拟线程处理请求，和 Callable<T> 返回类型方法表现一致。
     * </pre>
     */
    @Async
    @GetMapping("/asyncCompletableFuture")
    public CompletableFuture<String> asyncCompletableFuture() {
        // 打印线程名称
        String ts = Thread.currentThread().toString();
        System.out.println(ts);
        return CompletableFuture.completedFuture("asyncCompletableFuture result");
    }


}
